//
//  ImageCache.swift
//  图片缓存
//
//  Created by emma on 2024/4/20.
//

import UIKit

class ImageCache {
    static let shared = ImageCache()
    private var cache = NSCache<AnyObject, AnyObject>()
    
    func loadImage(url: String, complete: @escaping (_ image: UIImage?) -> ()) {
        DispatchQueue.global().async {
            /// 先找内存
            var image: UIImage? = self.cache.object(forKey: self.getImageName(from: url) as AnyObject) as? UIImage
            if let image = image {
                DispatchQueue.main.async { complete(image) }
                return
            }
            /// 再找本地
            image = self.readImageFromSandbox(url: url)
            if let image = image {
                DispatchQueue.main.async { complete(image) }
                // 写入内存
                self.whiteImageToCache(url: url, image: image)
                return
            }
            /// 最后从网络下载
            HttpRequest.shared.download(url) { (data) in
                MyLog(data)
                image = UIImage(data: data)
                if let image = image {
                    DispatchQueue.main.async { complete(image) }
                    // 写入内存
                    self.whiteImageToCache(url: url, image: image)
                    // 写入本地
                    self.writeImageToSandbox(url: url, data: data)
                }else {
                    DispatchQueue.main.async { complete(nil) }
                }
                return
            }failure: { (error) in
                DispatchQueue.main.async { complete(nil) }
            }
        }
    }
    
    // 清除缓存
    func clear() {
        MyLog(self.cache)
        self.cache.removeAllObjects()
    }
    
    // 写入照片到内存
    private func whiteImageToCache(url: String, image: UIImage) {
        let key = self.getImageName(from: url)
        self.cache.setObject(image as AnyObject, forKey: key as AnyObject)
    }
    
    // 写入照片到沙盒
    private func writeImageToSandbox(url: String, data: Data) {
        let adPhotoPath:String = NSHomeDirectory() + "/Documents/" + "ImageCache/"
        let imagePath = adPhotoPath + getImageName(from: url)
        
        if FileManager.default.fileExists(atPath: imagePath) { return }
        
        let fileManager = FileManager.default
        if !fileManager.fileExists(atPath: adPhotoPath) {//文件夹不存在，先创建文件夹
            do {
                //withIntermediateDirectories为ture表示路径中间如果有不存在的文件夹都会创建
                try fileManager.createDirectory(atPath: adPhotoPath, withIntermediateDirectories: true, attributes: nil)
            } catch let error {
                print(error.localizedDescription)
            }
        }
        
        do {
            try data.write(to: URL(fileURLWithPath: imagePath))
        } catch let error {
            print(error.localizedDescription)
        }
    }
    
    // 本地沙盒查找Sandbox
    private func readImageFromSandbox(url: String) -> UIImage? {
        let adPhotoPath: String = NSHomeDirectory() + "/Documents/" + "ImageCache/"
        let imagePath = adPhotoPath + getImageName(from: url)
        if !FileManager.default.fileExists(atPath: imagePath)
        {
            return nil
        }
        
        let data = FileManager.default.contents(atPath: imagePath)
        if data == nil
        {
            return nil
        }
        return UIImage(data: data!)
    }
    
    // 通过图片URL计算得出一个35位的图片名，再去本地找
    private func getImageName(from url: String) -> String {
        // url过长，不能写入，先转一下Base64
        let utf8EncodeData = url.data(using: String.Encoding.utf8, allowLossyConversion: true)
        // 将NSData进行Base64编码
        var base64String = utf8EncodeData?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: UInt(0)))
        base64String = base64String?.replacingOccurrences(of: "=", with: "")
        base64String = base64String?.replacingOccurrences(of: "+", with: "")
        base64String = base64String?.replacingOccurrences(of: "/", with: "")
        //MyLog(base64String)
        // 取前15位+后20位作为图片名
        return base64String!.prefix(15) + base64String!.suffix(20) + ".png"
    }
    
    /// 根据尺寸重新生成图片
    /// - Parameter size: 设置的大小
    /// - Returns: 新图
    public func imageWithNewSize(image: UIImage, size: CGSize) -> Data? {
        if image.size.width > size.width {
            let height = size.width / image.size.width * image.size.height
            let newImgSize = CGSize(width: size.width, height: height)
            //UIGraphicsBeginImageContextWithOptions(<#T##size: CGSize##CGSize#>, <#T##opaque: Bool##Bool#>, <#T##scale: CGFloat##CGFloat#>) 这个可以设置背景图的透明度
            UIGraphicsBeginImageContext(newImgSize)
            image.draw(in: CGRect(x: 0, y: 0, width: newImgSize.width, height: newImgSize.height))
            let theImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            guard let newImg = theImage else { return  image.jpegData(compressionQuality: 1.0)}
            return newImg.jpegData(compressionQuality: 1.0)
        } else {
            return image.jpegData(compressionQuality: 1.0)
        }
    }
}
